<!-- 表单 》 密码框 -->

<template>
  <el-form-item v-bind="formItem">
    <!-- 标签 -->
    <template v-if="hasLabelSlot" #label>
      <slot name="label" :label="formItem.label">{{ formItem.label }}</slot>
    </template>

    <el-input
      v-model.trim="model"
      v-bind="commonProps"
      :maxlength="max"
      show-password
      @input="emitChange"
      @blur="emitChange"
      @keyup.enter.native="toEnter"
    />
  </el-form-item>
</template>

<script>
// ============================== 导入依赖 ============================== //

import CORE from '@/CORE'
import mixForm from '../mixForm'
import FormInput from '../FormInput'

const name = 'FormPassword'

// ============================== 导出组件 ============================== //

export default {
  /**
   * 名称定义 (实际使用名称)
   */
  name,

  /**
   * 混入列表 (配置选项合并)
   */
  mixins: [mixForm],

  /**
   * 属性注册 (抽取以便查阅)
   */
  props: CORE.WEB[name],

  /**
   * 状态数据 (函数返回对象)
   */
  data() {
    return FormInput.data()
  },

  /**
   * 计算属性 (慎用箭头函数)
   */
  computed: {
    /**
     * 校验方法
     */
    validator() {
      const { check, min, same, letter, upper, lower, number, special, noSpecial, noChinese, two, three, all } = this
      const need = check || min || same || letter || upper || lower || number || special || noSpecial || noChinese ||
        two || three || all
      if (!need) return null

      return (rule, value, callback) => {
        if (!value) return callback()

        const errMsg = check ? check(value) : ''
        const hasUpper = /[A-Z]/.test(value)
        const hasLower = /[a-z]/.test(value)
        const hasNumber = /\d/.test(value)
        const hasSpecial = /[^a-zA-Z0-9]/.test(value)
        const hasSpecialChars = !this.specialChars || this.specialChars.split('').some((x) => value.includes(x))
        const hasChinese = /[\u4e00-\u9fa5]/.test(value)
        const count = hasUpper + hasLower + hasNumber + hasSpecial
        const specialCharsErr = this.specialCharsErr.replace('{specialChars}', this.specialChars)

        if (errMsg) callback(new Error(errMsg))
        else if (min && value.length < min) callback(new Error(this.minErr.replace('{min}', min)))
        else if (same && value !== this.obj[same]) callback(new Error(this.sameErr))
        else if (letter && !hasUpper && !hasLower) callback(new Error(this.letterErr))
        else if (upper && !hasUpper) callback(new Error(this.upperErr))
        else if (lower && !hasLower) callback(new Error(this.lowerErr))
        else if (number && !hasNumber) callback(new Error(this.numberErr))
        else if (special && !hasSpecial) callback(new Error(this.specialErr))
        else if (noSpecial && hasSpecial) callback(new Error(this.noSpecialErr))
        else if (noChinese && hasChinese) callback(new Error(this.noChineseErr))
        else if (two && count < 2) callback(new Error(this.twoErr))
        else if (three && count < 3) callback(new Error(this.threeErr))
        else if (all && count < 4) callback(new Error(this.allErr))
        else if ((special || all) && !hasSpecialChars) callback(new Error(specialCharsErr))
        else callback()
      }
    },
  },

  /**
   * 本地方法 (轻量重要在前)
   */
  methods: {
    /**
     * 回车事件
     */
    toEnter: FormInput.methods.toEnter,
  },
}
</script>
